using System;
using System.Collections.Generic;

namespace Measurements
{
    /// <summary>
    /// A unit of mass.
    /// </summary>
    public class MassUnit : MeasurementUnit
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Measurements.MassUnit"/> class.
        /// </summary>
        /// <param name='name'>
        /// The name of the unit.
        /// </param>
        /// <param name='unit'>
        /// The abbreviation of the unit.
        /// </param>
        /// <param name='toBaseUnit'>
        /// The delegate that converts values in this unit to values in the base unit.
        /// </param>
        /// <param name='fromBaseUnit'>
        /// The delegate that converts values in the base unit to values in this unit.
        /// </param>
        public MassUnit(string name, string unit, ToBaseUnitDelegate toBaseUnit, FromBaseUnitDelegate fromBaseUnit)
            : base (name, unit, Mass.Kilogram, toBaseUnit, fromBaseUnit) { }           
    }
    
    /// <summary>
    /// A unit of mass directly related to the base SI unit.
    /// </summary>
    public class SiMassUnit : MassUnit
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Measurements.SiMassUnit"/> class.
        /// </summary>
        /// <param name='name'>
        /// The name of the unit.
        /// </param>
        /// <param name='unit'>
        /// The abbreviation of the unit.
        /// </param>
        /// <param name='factor'>
        /// The factor used to convert values in this unit to values in the base unit.
        /// </param>
        public SiMassUnit(string name, string unit, double factor)
            : base(name, unit, m => m * factor, m => m / factor) { }
    }     
    
    /// <summary>
    /// A measurement of mass.
    /// </summary>
    public class Mass : Measurement<Mass, MassUnit>
    {
        /// <summary>
        /// The kilogram, the base SI unit of mass.
        /// </summary>
        public static MassUnit Kilogram = new MassUnit("kilogram", "kg", m => m, m => m);
        
        /// <summary>
        /// The gram, one one-thousandth of a kilogram.
        /// </summary>
        public static MassUnit Gram = new SiMassUnit("gram", "g", 1e-3);
        
        /// <summary>
        /// The tonne, one thousand kilograms.
        /// </summary>
        public static MassUnit Tonne = new SiMassUnit("tonne", "t", 1e3);
        
        /// <summary>
        /// The international avoirdupois pound.
        /// </summary>
        public static MassUnit Pound = new MassUnit("pound", "lbm", m => m * 0.45359237, m => m / 0.45359237);
        
        /// <summary>
        /// Gets a collection of Mass units.
        /// </summary>
        public static IEnumerable<MassUnit> Units
        {
            get
            {
                yield return Kilogram;
                yield return Gram;
                yield return Tonne;
                yield return Pound;
            }
        }        
    }
}
